export interface GameResource {
  key: string
  type: 'image' | 'audio' | 'font' | 'json' | 'spritesheet'
  url: string
  config?: any
}

export class ResourceLoader {
  private resources: Map<string, GameResource> = new Map()
  private loadedResources: Set<string> = new Set()
  private isLoading: boolean = false

  constructor() {
    this.initializeResources()
  }

  /**
   * 初始化游戏资源列表
   */
  private initializeResources(): void {
    // 基础图片资源
    this.addResource({
      key: 'player',
      type: 'image',
      url: '/assets/images/player.png',
    })

    this.addResource({
      key: 'enemy',
      type: 'image',
      url: '/assets/images/enemy.png',
    })

    this.addResource({
      key: 'tileset',
      type: 'image',
      url: '/assets/images/tileset.png',
    })

    this.addResource({
      key: 'ui-buttons',
      type: 'spritesheet',
      url: '/assets/images/ui-buttons.png',
      config: {
        frameWidth: 64,
        frameHeight: 32,
      },
    })

    // 音频资源
    this.addResource({
      key: 'bgm-menu',
      type: 'audio',
      url: '/assets/audio/bgm-menu.mp3',
    })

    this.addResource({
      key: 'bgm-game',
      type: 'audio',
      url: '/assets/audio/bgm-game.mp3',
    })

    this.addResource({
      key: 'sfx-click',
      type: 'audio',
      url: '/assets/audio/sfx-click.mp3',
    })

    this.addResource({
      key: 'sfx-attack',
      type: 'audio',
      url: '/assets/audio/sfx-attack.mp3',
    })

    // 字体资源
    this.addResource({
      key: 'game-font',
      type: 'font',
      url: '/assets/fonts/game-font.woff2',
    })

    // 配置文件
    this.addResource({
      key: 'game-config',
      type: 'json',
      url: '/assets/config/game-config.json',
    })
  }

  /**
   * 添加资源
   */
  addResource(resource: GameResource): void {
    this.resources.set(resource.key, resource)
  }

  /**
   * 初始化资源加载器
   */
  async init(): Promise<void> {
    if (this.isLoading) {
      console.warn('ResourceLoader already initializing')
      return
    }

    this.isLoading = true
    console.log('Starting resource loading...')

    try {
      // 预加载关键资源
      await this.preloadCriticalResources()

      // 加载其他资源
      await this.loadAllResources()

      console.log('All resources loaded successfully')
    } catch (error) {
      console.error('Failed to load resources:', error)
      throw error
    } finally {
      this.isLoading = false
    }
  }

  /**
   * 预加载关键资源
   */
  private async preloadCriticalResources(): Promise<void> {
    const criticalResources = ['player', 'tileset', 'ui-buttons']

    for (const key of criticalResources) {
      const resource = this.resources.get(key)
      if (resource) {
        await this.loadResource(resource)
      }
    }
  }

  /**
   * 加载所有资源
   */
  private async loadAllResources(): Promise<void> {
    const loadPromises = Array.from(this.resources.values()).map((resource) =>
      this.loadResource(resource),
    )

    await Promise.all(loadPromises)
  }

  /**
   * 加载单个资源
   */
  private async loadResource(resource: GameResource): Promise<void> {
    if (this.loadedResources.has(resource.key)) {
      return
    }

    try {
      switch (resource.type) {
        case 'image':
          await this.loadImage(resource)
          break
        case 'audio':
          await this.loadAudio(resource)
          break
        case 'font':
          await this.loadFont(resource)
          break
        case 'json':
          await this.loadJSON(resource)
          break
        case 'spritesheet':
          await this.loadSpritesheet(resource)
          break
      }

      this.loadedResources.add(resource.key)
      console.log(`Resource '${resource.key}' loaded successfully`)
    } catch (error) {
      console.error(`Failed to load resource '${resource.key}':`, error)
      throw error
    }
  }

  /**
   * 加载图片资源
   */
  private async loadImage(resource: GameResource): Promise<void> {
    return new Promise((resolve, reject) => {
      const img = new Image()
      img.onload = () => resolve()
      img.onerror = () => reject(new Error(`Failed to load image: ${resource.url}`))
      img.src = resource.url
    })
  }

  /**
   * 加载音频资源
   */
  private async loadAudio(resource: GameResource): Promise<void> {
    return new Promise((resolve, reject) => {
      const audio = new Audio()
      audio.oncanplaythrough = () => resolve()
      audio.onerror = () => reject(new Error(`Failed to load audio: ${resource.url}`))
      audio.src = resource.url
    })
  }

  /**
   * 加载字体资源
   */
  private async loadFont(resource: GameResource): Promise<void> {
    return new Promise((resolve, reject) => {
      const fontFace = new FontFace('GameFont', `url(${resource.url})`)
      fontFace
        .load()
        .then(() => {
          document.fonts.add(fontFace)
          resolve()
        })
        .catch(() => reject(new Error(`Failed to load font: ${resource.url}`)))
    })
  }

  /**
   * 加载JSON资源
   */
  private async loadJSON(resource: GameResource): Promise<void> {
    const response = await fetch(resource.url)
    if (!response.ok) {
      throw new Error(`Failed to load JSON: ${resource.url}`)
    }
    await response.json()
  }

  /**
   * 加载精灵表资源
   */
  private async loadSpritesheet(resource: GameResource): Promise<void> {
    // 精灵表实际上是图片，所以使用图片加载方式
    await this.loadImage(resource)
  }

  /**
   * 检查资源是否已加载
   */
  isResourceLoaded(key: string): boolean {
    return this.loadedResources.has(key)
  }

  /**
   * 获取已加载的资源数量
   */
  getLoadedResourceCount(): number {
    return this.loadedResources.size
  }

  /**
   * 获取总资源数量
   */
  getTotalResourceCount(): number {
    return this.resources.size
  }

  /**
   * 获取加载进度
   */
  getLoadingProgress(): number {
    if (this.resources.size === 0) return 100
    return (this.loadedResources.size / this.resources.size) * 100
  }

  /**
   * 检查是否正在加载
   */
  isLoadingResources(): boolean {
    return this.isLoading
  }
}
